namespace Webinator.DomTraversal
{
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using Webinator.Enums;
    using Webinator.Impls;
    using Webinator.Interfaces;
    using Webinator.MultipleAttribute;
    using Webinator.Toolboxes;

    // TODO: PrecededBy, FollowedBy, GetPrecedingSibling, GetFollowingSibling, GetParent/GetAncestor
    // TODO: Attributes need value comparisons?

    /// <summary>
    /// Multiple node <c>Locator</c> builder.
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Reviewed. Suppression is OK here.")]
    public class DomNode
    {
        private readonly IWebManager _webManager;
        private string _html;

        /// <summary>
        /// The nodes.
        /// </summary>
        private List<XpathNode> _xpathNodes;

        internal DomNode(IWebManager webManager)
        {
            _webManager = webManager;
            _html = webManager.PageSource();
        }

        internal DomNode(string html)
        {
            _webManager = null;
            _html = html;
        }

        internal DomNode(string html, IWebManager webManager)
        {
            _html = html;
            _webManager = webManager;
        }

        /// <summary>
        /// Gets or sets the nodes.
        /// </summary>
        internal List<XpathNode> XpathNodes
        {
            get { return _xpathNodes ?? (_xpathNodes = new List<XpathNode>()); }
            set { _xpathNodes = value; }
        }

        public Locator Locator
        {
            get
            {
                return LocateBy.Xpath(Xpath);
            }
        }

        public string Xpath
        {
            get { return XPathToolbox.GetXpathFromDomNode(this); }
        }

        #region Properties

        public DomNodes Anchors
        {
            get { return ReturnDomNodes(NodeIs.Anchor); }
        }

        public DomNode Body
        {
            get { return ReturnDomNode(NodeIs.Body); }
        }

        public DomNodes Buttons
        {
            get { return ReturnDomNodes(NodeIs.Button); }
        }

        public DomNodes Captions
        {
            get { return ReturnDomNodes(NodeIs.Caption); }
        }

        public DomNodes Columns
        {
            get { return ReturnDomNodes(NodeIs.Column); }
        }

        public DomNodes ColumnGroups
        {
            get { return ReturnDomNodes(NodeIs.ColumnGroup); }
        }

        public DomNodes Divs
        {
            get { return ReturnDomNodes(NodeIs.Div); }
        }

        public DomNodes Fieldsets
        {
            get { return ReturnDomNodes(NodeIs.Fieldset); }
        }

        public DomNodes Forms
        {
            get { return ReturnDomNodes(NodeIs.Form); }
        }

        public DomNode Head
        {
            get { return ReturnDomNode(NodeIs.Head); }
        }

        public DomNode Html
        {
            get { return ReturnDomNode(NodeIs.Html); }
        }

        public DomNodes Images
        {
            get { return ReturnDomNodes(NodeIs.Image); }
        }

        public DomNodes Inputs
        {
            get { return ReturnDomNodes(NodeIs.Input); }
        }

        public DomNodes Textboxes
        {
            get { return ReturnDomNodes(NodeIs.Input, ByAttribute.Type("text")); }
        }

        public DomNodes PasswordFields
        {
            get { return ReturnDomNodes(NodeIs.Input, ByAttribute.Type("password")); }
        }

        public DomNodes SubmitButtons
        {
            get { return ReturnDomNodes(NodeIs.Input, ByAttribute.Type("submit")); }
        }

        public DomNodes Checkboxes
        {
            get { return ReturnDomNodes(NodeIs.Input, ByAttribute.Type("checkbox")); }
        }

        public DomNodes Radios
        {
            get { return ReturnDomNodes(NodeIs.Input, ByAttribute.Type("radio")); }
        }

        public DomNodes Labels
        {
            get { return ReturnDomNodes(NodeIs.Label); }
        }

        public DomNodes ListItems
        {
            get { return ReturnDomNodes(NodeIs.ListItem); }
        }

        public DomNodes OrderedLists
        {
            get { return ReturnDomNodes(NodeIs.OrderedList); }
        }

        public DomNodes UnorderedLists
        {
            get { return ReturnDomNodes(NodeIs.UnorderedList); }
        }

        public DomNodes OptionGroups
        {
            get { return ReturnDomNodes(NodeIs.OptionGroup); }
        }

        public DomNodes Options
        {
            get { return ReturnDomNodes(NodeIs.Option); }
        }

        public DomNodes Paragraphs
        {
            get { return ReturnDomNodes(NodeIs.Paragraph); }
        }

        public DomNodes SelectLists
        {
            get { return ReturnDomNodes(NodeIs.Select); }
        }

        public DomNodes Spans
        {
            get { return ReturnDomNodes(NodeIs.Span); }
        }

        public DomNodes Tables
        {
            get { return ReturnDomNodes(NodeIs.Table); }
        }

        public DomNodes TableBodies
        {
            get { return ReturnDomNodes(NodeIs.TableBody); }
        }

        public DomNodes TableCells
        {
            get { return ReturnDomNodes(NodeIs.TableCell); }
        }

        public DomNodes TableRows
        {
            get { return ReturnDomNodes(NodeIs.TableRow); }
        }

        public DomNodes Textareas
        {
            get { return ReturnDomNodes(NodeIs.Textarea); }
        }

        public DomNodes TableFooters
        {
            get { return ReturnDomNodes(NodeIs.TableFooter); }
        }

        public DomNodes TableHeaderCells
        {
            get { return ReturnDomNodes(NodeIs.TableHeaderCell); }
        }

        public DomNodes TableHeaders
        {
            get { return ReturnDomNodes(NodeIs.TableHeader); }
        }

        public DomNode Title
        {
            get { return ReturnDomNode(NodeIs.Title); }
        }

        #endregion

        #region Locator Actions

        public bool Exists
        {
            get { return _webManager.Exists(Locator); }
        }

        public bool IsSelected
        {
            get { return _webManager.IsSelected(Locator); }
        }

        public bool IsVisible
        {
            get { return _webManager.IsVisible(Locator); }
        }

        public string Text
        {
            get
            {
                return _webManager.GetText(Locator);
            }
        }

        public string Value
        {
            get
            {
                return _webManager.GetAttribute(Locator, "value");
            }
        }

        public string InnerText
        {
            get
            {
                var text = XPathToolbox.GetNodes(_webManager.PageSource(), Xpath)[0].InnerText;
                return text;
            }
        }

        public string InnerHtml
        {
            get
            {
                var text = XPathToolbox.GetNodes(_webManager.PageSource(), Xpath)[0].InnerHtml;
                return text;
            }
        }

        public string OuterHtml
        {
            get
            {
                var text = XPathToolbox.GetNodes(_webManager.PageSource(), Xpath)[0].OuterHtml;
                return text;
            }
        }

        public string Class
        {
            get
            {
                var text = XPathToolbox.GetNodes(_webManager.PageSource(), Xpath)[0].GetAttributeValue("class", string.Empty);
                return text;
            }
        }

        public string Id
        {
            get
            {
                var text = XPathToolbox.GetNodes(_webManager.PageSource(), Xpath)[0].Id;
                return text;
            }
        }

        public string Name
        {
            get
            {
                var text = XPathToolbox.GetNodes(_webManager.PageSource(), Xpath)[0].Name;
                return text;
            }
        }

        public IWebManager AppendText(string text, ICondition condition = null)
        {
            _webManager.AppendText(Locator, text, condition);
            return _webManager;
        }

        public IWebManager Clear(ICondition condition = null)
        {
            _webManager.Clear(Locator, condition);
            return _webManager;
        }

        public IWebManager Click(ICondition condition = null)
        {
            _webManager.Click(Locator, condition);
            return _webManager;
        }

        public string GetAttribute(string attribute)
        {
            var attr = XPathToolbox.GetNodes(_webManager.PageSource(), Xpath)[0].GetAttributeValue(attribute, string.Empty);
            return attr;
        }

        public SelectedItem GetSelectedItemFromCollection()
        {
            return _webManager.GetSelectedElementFromCollection(Locator);
        }

        public IEnumerable<SelectedItem> GetSelectedItemsFromCollection()
        {
            return _webManager.GetSelectedElementsFromCollection(Locator);
        }

        public SelectedItem GetSelectedListItem()
        {
            return _webManager.GetSelectedListItem(Locator);
        }

        public IEnumerable<SelectedItem> GetSelectedListItems()
        {
            return _webManager.GetSelectedListItems(Locator);
        }

        public IWebManager Highlight()
        {
            _webManager.Highlight(Locator);
            return _webManager;
        }

        public IWebManager SelectCheckbox(bool check, ICondition condition = null)
        {
            _webManager.SelectCheckbox(Locator, check, condition);
            return _webManager;
        }

        public IWebManager SelectListItem(ICondition condition, params Selector[] selectors)
        {
            _webManager.SelectListItem(Locator, condition, selectors);

            return _webManager;
        }

        public IWebManager SelectListItem(params Selector[] selectors)
        {
            _webManager.SelectListItem(Locator, selectors);

            return _webManager;
        }

        public IWebManager SelectRadio(ICondition condition = null)
        {
            _webManager.SelectRadio(Locator, condition);
            return _webManager;
        }

        public IWebManager SendKeys(string text, ICondition condition = null)
        {
            _webManager.SendKeys(Locator, text, condition);
            return _webManager;
        }

        public IWebManager SetAttribute(string attribute, string value)
        {
            _webManager.SetAttribute(Locator, attribute, value);
            return _webManager;
        }

        public IWebManager SetText(string text)
        {
            _webManager.SetText(Locator, text);
            return _webManager;
        }

        public IWebManager UnHighlight()
        {
            _webManager.Highlight(Locator, true);
            return _webManager;
        }

        #endregion

        #region Dom Elements

        public DomNode First()
        {
            return ReturnDomNode(NodeIs.First);
        }

        public DomNode Last()
        {
            return ReturnDomNode(NodeIs.Last);
        }

        public DomNode Position(int position)
        {
            return ReturnDomNode(NodeIs.Position, position.ToString(CultureInfo.InvariantCulture));
        }

        public DomNode Anchor(string value)
        {
            return ReturnDomNode(NodeIs.Anchor, value);
        }

        public DomNode Anchor(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Anchor, value, contains);
        }

        public DomNode Anchor(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Anchor, definedAttributes);
        }

        public DomNode Button(string value)
        {
            return ReturnDomNode(NodeIs.Button, value);
        }

        public DomNode Button(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Button, value, contains);
        }

        public DomNode Button(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Button, definedAttributes);
        }

        public DomNode Caption(string value)
        {
            return ReturnDomNode(NodeIs.Caption, value);
        }

        public DomNode Caption(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Caption, value, contains);
        }

        public DomNode Caption(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Caption, definedAttributes);
        }

        public DomNode Column(string value)
        {
            return ReturnDomNode(NodeIs.Column, value);
        }

        public DomNode Column(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Column, value, contains);
        }

        public DomNode Column(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Column, definedAttributes);
        }

        public DomNode ColumnGroup(string value)
        {
            return ReturnDomNode(NodeIs.ColumnGroup, value);
        }

        public DomNode ColumnGroup(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.ColumnGroup, value, contains);
        }

        public DomNode ColumnGroup(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.ColumnGroup, definedAttributes);
        }

        public DomNode Div(string value)
        {
            return ReturnDomNode(NodeIs.Div, value);
        }

        public DomNode Div(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Div, value, contains);
        }

        public DomNode Div(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Div, definedAttributes);
        }

        public DomNode Fieldset(string value)
        {
            return ReturnDomNode(NodeIs.Fieldset, value);
        }

        public DomNode Fieldset(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Fieldset, value, contains);
        }

        public DomNode Fieldset(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Fieldset, definedAttributes);
        }

        public DomNode Form(string value)
        {
            return ReturnDomNode(NodeIs.Form, value);
        }

        public DomNode Form(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Form, value, contains);
        }

        public DomNode Form(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Form, definedAttributes);
        }

        public DomNode Image(string value)
        {
            return ReturnDomNode(NodeIs.Image, value);
        }

        public DomNode Image(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Image, value, contains);
        }

        public DomNode Image(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Image, definedAttributes);
        }

        public DomNode Input(string value)
        {
            return ReturnDomNode(NodeIs.Input, value);
        }

        public DomNode Input(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Input, value, contains);
        }

        public DomNode Input(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Input, definedAttributes);
        }

        public DomNode Textbox(string value)
        {
            return ReturnDomNode(NodeIs.Input, ByAttribute.Type("text").AndAny(value));
        }

        public DomNode Textbox(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Input, ByAttribute.Type("text").AndAny(value, contains));
        }

        public DomNode Textbox(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Input, definedAttributes.AndType("text"));
        }

        public DomNode PasswordField(string value)
        {
            return ReturnDomNode(NodeIs.Input, ByAttribute.Type("password").AndAny(value));
        }

        public DomNode PasswordField(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Input, ByAttribute.Type("password").AndAny(value, contains));
        }

        public DomNode PasswordField(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Input, definedAttributes.AndType("password"));
        }

        public DomNode SubmitButton(string value)
        {
            return ReturnDomNode(NodeIs.Input, ByAttribute.Type("submit").AndAny(value));
        }

        public DomNode SubmitButton(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Input, ByAttribute.Type("submit").AndAny(value, contains));
        }

        public DomNode SubmitButton(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Input, definedAttributes.AndType("submit"));
        }

        public DomNode Checkbox(string value)
        {
            return ReturnDomNode(NodeIs.Input, ByAttribute.Type("checkbox").AndAny(value));
        }

        public DomNode Checkbox(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Input, ByAttribute.Type("checkbox").AndAny(value, contains));
        }

        public DomNode Checkbox(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Input, definedAttributes.AndType("checkbox"));
        }

        public DomNode Radio(string value)
        {
            return ReturnDomNode(NodeIs.Input, ByAttribute.Type("radio").AndAny(value));
        }

        public DomNode Radio(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Input, ByAttribute.Type("radio").AndAny(value, contains));
        }

        public DomNode Radio(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Input, definedAttributes.AndType("radio"));
        }

        public DomNode Label(string value)
        {
            return ReturnDomNode(NodeIs.Label, value);
        }

        public DomNode Label(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Label, value, contains);
        }

        public DomNode Label(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Label, definedAttributes);
        }

        public DomNode ListItem(string value)
        {
            return ReturnDomNode(NodeIs.ListItem, value);
        }

        public DomNode ListItem(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.ListItem, value, contains);
        }

        public DomNode ListItem(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.ListItem, definedAttributes);
        }

        public DomNode OrderedList(string value)
        {
            return ReturnDomNode(NodeIs.OrderedList, value);
        }

        public DomNode OrderedList(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.OrderedList, value, contains);
        }

        public DomNode OrderedList(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.OrderedList, definedAttributes);
        }

        public DomNode OptionGroup(string value)
        {
            return ReturnDomNode(NodeIs.OptionGroup, value);
        }

        public DomNode OptionGroup(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.OptionGroup, value, contains);
        }

        public DomNode OptionGroup(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.OptionGroup, definedAttributes);
        }

        public DomNode Option(string value)
        {
            return ReturnDomNode(NodeIs.Option, value);
        }

        public DomNode Option(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Option, value, contains);
        }

        public DomNode Option(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Option, definedAttributes);
        }

        public DomNode Paragraph(string value)
        {
            return ReturnDomNode(NodeIs.Paragraph, value);
        }

        public DomNode Paragraph(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Paragraph, value, contains);
        }

        public DomNode Paragraph(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Paragraph, definedAttributes);
        }

        public DomNode SelectList(string value)
        {
            return ReturnDomNode(NodeIs.Select, value);
        }

        public DomNode SelectList(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Select, value, contains);
        }

        public DomNode SelectList(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Select, definedAttributes);
        }

        public DomNode Span(string value)
        {
            return ReturnDomNode(NodeIs.Span, value);
        }

        public DomNode Span(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Span, value, contains);
        }

        public DomNode Span(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Span, definedAttributes);
        }

        public DomNode Table(string value)
        {
            return ReturnDomNode(NodeIs.Table, value);
        }

        public DomNode Table(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Table, value, contains);
        }

        public DomNode Table(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Table, definedAttributes);
        }

        public DomNode TableBody(string value)
        {
            return ReturnDomNode(NodeIs.TableBody, value);
        }

        public DomNode TableBody(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.TableBody, value, contains);
        }

        public DomNode TableBody(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.TableBody, definedAttributes);
        }

        public DomNode TableCell(string value)
        {
            return ReturnDomNode(NodeIs.TableCell, value);
        }

        public DomNode TableCell(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.TableCell, value, contains);
        }

        public DomNode TableCell(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.TableCell, definedAttributes);
        }

        public DomNode Textarea(string value)
        {
            return ReturnDomNode(NodeIs.Textarea, value);
        }

        public DomNode Textarea(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Textarea, value, contains);
        }

        public DomNode Textarea(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Textarea, definedAttributes);
        }

        public DomNode TableFoot(string value)
        {
            return ReturnDomNode(NodeIs.TableFooter, value);
        }

        public DomNode TableFoot(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.TableFooter, value, contains);
        }

        public DomNode TableFoot(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.TableFooter, definedAttributes);
        }

        public DomNode TableHeaderCell(string value)
        {
            return ReturnDomNode(NodeIs.TableHeaderCell, value);
        }

        public DomNode TableHeaderCell(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.TableHeaderCell, value, contains);
        }

        public DomNode TableHeaderCell(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.TableHeaderCell, definedAttributes);
        }

        public DomNode TableHeader(string value)
        {
            return ReturnDomNode(NodeIs.TableHeader, value);
        }

        public DomNode TableHeader(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.TableHeader, value, contains);
        }

        public DomNode TableHeader(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.TableHeader, definedAttributes);
        }

        public DomNode TableRow(string value)
        {
            return ReturnDomNode(NodeIs.TableRow, value);
        }

        public DomNode TableRow(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.TableRow, value, contains);
        }

        public DomNode TableRow(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.TableRow, definedAttributes);
        }

        public DomNode UnorderedList(string value)
        {
            return ReturnDomNode(NodeIs.UnorderedList, value);
        }

        public DomNode UnorderedList(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.UnorderedList, value, contains);
        }

        public DomNode UnorderedList(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.UnorderedList, definedAttributes);
        }

        public DomNode Any(string value)
        {
            return ReturnDomNode(NodeIs.Any, value);
        }

        public DomNode Any(string value, bool contains)
        {
            return ReturnDomNode(NodeIs.Any, value, contains);
        }

        public DomNode Any(DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(NodeIs.Any, definedAttributes);
        }

        public DomNode Custom(string node)
        {
            return ReturnDomNode(node);
        }

        public DomNode Custom(string node, string value)
        {
            return ReturnDomNode(node, value);
        }

        public DomNode Custom(string node, string value, bool contains)
        {
            return ReturnDomNode(node, value, contains);
        }

        public DomNode Custom(string node, DefinedAttributes definedAttributes)
        {
            return ReturnDomNode(node, definedAttributes);
        }

        #endregion

        #region Helpers

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="nodeIs">The attribute.</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNode ReturnDomNode(NodeIs nodeIs)
        {
            XpathNodes.Add(new XpathNode(nodeIs));
            return this;
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="nodeIs">The attribute.</param>
        /// <param name="value">The value.</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNode ReturnDomNode(NodeIs nodeIs, string value)
        {
            XpathNodes.Add(new XpathNode(nodeIs, value));
            return this;
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="nodeIs">The attribute.</param>
        /// <param name="value">The value.</param>
        /// <param name="contains">Indicates whether the attribute value should be an exact match.</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNode ReturnDomNode(NodeIs nodeIs, string value, bool contains)
        {
            XpathNodes.Add(new XpathNode(nodeIs, value, contains));
            return this;
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="nodeIs">The attribute.</param>
        /// <param name="definedAttributes">The attribute(s) to use when locating the element(s).</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNode ReturnDomNode(NodeIs nodeIs, DefinedAttributes definedAttributes)
        {
            XpathNodes.Add(new XpathNode(nodeIs, definedAttributes));
            return this;
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="node">The attribute.</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNode ReturnDomNode(string node)
        {
            XpathNodes.Add(new XpathNode(node));
            return this;
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="node">The attribute.</param>
        /// <param name="value">The value.</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNode ReturnDomNode(string node, string value)
        {
            XpathNodes.Add(new XpathNode(node, value));
            return this;
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="node">The attribute.</param>
        /// <param name="value">The value.</param>
        /// <param name="contains">Indicates whether the attribute value should be an exact match.</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNode ReturnDomNode(string node, string value, bool contains)
        {
            XpathNodes.Add(new XpathNode(node, value, contains));
            return this;
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="node">The attribute.</param>
        /// <param name="definedAttributes">The attribute(s) to use when locating the element(s).</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNode ReturnDomNode(string node, DefinedAttributes definedAttributes)
        {
            XpathNodes.Add(new XpathNode(node, definedAttributes));
            return this;
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="nodeIs">The attribute.</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNodes ReturnDomNodes(NodeIs nodeIs)
        {
            var dn = new DomNodes(_html, _webManager);
            dn.XpathNodes.AddRange(XpathNodes);
            return dn.ReturnDomNodes(nodeIs);
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="nodeIs">The attribute.</param>
        /// <param name="value">The value.</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNodes ReturnDomNodes(NodeIs nodeIs, string value)
        {
            var dn = new DomNodes(_html, _webManager);
            dn.XpathNodes.AddRange(XpathNodes);
            return dn.ReturnDomNodes(nodeIs, value);
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="nodeIs">The attribute.</param>
        /// <param name="value">The value.</param>
        /// <param name="contains">Indicates whether the attribute value should be an exact match.</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNodes ReturnDomNodes(NodeIs nodeIs, string value, bool contains)
        {
            var dn = new DomNodes(_html, _webManager);
            dn.XpathNodes.AddRange(XpathNodes);
            return dn.ReturnDomNodes(nodeIs, value, contains);
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="nodeIs">The attribute.</param>
        /// <param name="definedAttributes">The attribute(s) to use when locating the element(s).</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNodes ReturnDomNodes(NodeIs nodeIs, DefinedAttributes definedAttributes)
        {
            var dn = new DomNodes(_html, _webManager);
            dn.XpathNodes.AddRange(XpathNodes);
            return dn.ReturnDomNodes(nodeIs, definedAttributes);
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="node">The attribute.</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNodes ReturnDomNodes(string node)
        {
            var dn = new DomNodes(_html, _webManager);
            dn.XpathNodes.AddRange(XpathNodes);
            return dn.ReturnDomNodes(node);
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="node">The attribute.</param>
        /// <param name="value">The value.</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNodes ReturnDomNodes(string node, string value)
        {
            var dn = new DomNodes(_html, _webManager);
            dn.XpathNodes.AddRange(XpathNodes);
            return dn.ReturnDomNodes(node, value);
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="node">The attribute.</param>
        /// <param name="value">The value.</param>
        /// <param name="contains">Indicates whether the attribute value should be an exact match.</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNodes ReturnDomNodes(string node, string value, bool contains)
        {
            var dn = new DomNodes(_html, _webManager);
            dn.XpathNodes.AddRange(XpathNodes);
            return dn.ReturnDomNodes(node, value, contains);
        }

        /// <summary>
        /// Creates an instance of the <c>Defined Nodes</c> class.
        /// </summary>
        /// <param name="node">The attribute.</param>
        /// <param name="definedAttributes">The attribute(s) to use when locating the element(s).</param>
        /// <returns>
        /// An instance of the <c>Defined Nodes</c> class.
        /// </returns>
        internal DomNodes ReturnDomNodes(string node, DefinedAttributes definedAttributes)
        {
            var dn = new DomNodes(_html, _webManager);
            dn.XpathNodes.AddRange(XpathNodes);
            return dn.ReturnDomNodes(node, definedAttributes);
        }

        #endregion
    }
}